import { Graphics, GraphicsContext } from 'pixi.js';
import { BaseEntity, EntityFlags } from './BaseEntity';
import { PixijsRender } from '../PixijsRender';
import { ViewState } from './PixijsEntities';

export interface PathPoint {
    id: number;
    x: number;
    y: number;
}

export interface PathEntityOptions {
    lineWidth?: number;
    lineColor?: string;
    lineAlpha?: number;
}

export class PathEntity extends BaseEntity {
    points: { [id: number]: PathPoint } = {};
    path: number[][] = []
    lineWidth: number;
    lineColor: string;
    lineAlpha: number;
    leftType: number;
    rightType: number;
    private __viewDirty: boolean = true;

    constructor(pixiRender?: PixijsRender) {
        super(pixiRender);
        this.view = new Graphics(new GraphicsContext());
        this.leftType = 0;
        this.rightType = 0;
        this.setFlag(EntityFlags.Resize, false);
    }

    loadAssets(): void {
        super.loadAssets();
        this.viewState = ViewState.Showing;
    }

    onInit(options: PathEntityOptions) {
        this.lineWidth = options.lineWidth || 32;
        this.lineColor = options.lineColor || '#000000';
        this.lineAlpha = options.lineAlpha || 1;

    }

    insertPoint(p: PathPoint, pathIndex: number, pointIndex: number) {
        this.path[pathIndex].splice(pointIndex, 0, p.id);
        this.points[p.id] = p;
        this.__viewDirty = true;
        this.fixCenter();
    }

    deletePoint(pathIndex: number, pointIndex: number) {
        this.path[pathIndex].splice(pointIndex, 1);
        this.__viewDirty = true;
        this.fixCenter();
    }

    addPoint(p: { id: number; x: number; y: number; }) {
        this.points[p.id] = p;
        this.__viewDirty = true;
        this.fixCenter();
    }

    removePoint(point: PathPoint) {
        delete this.points[point.id];
        this.__viewDirty = true;
    }

    fixPath() {
        for(let i = this.path.length-1; i >= 0; i--) {
            let path = this.path[i];
            for(let j = path.length-1; j >= 0; j--) {
                let id = path[j];
                if(this.points[id] == undefined) {
                    path.splice(j, 1);
                    this.__viewDirty = true;
                }
            }
            if(path.length < 2) {
                this.path.splice(i, 1);
                this.__viewDirty = true;
            }
        }
        this.fixCenter();
    }

    drawPath() {       
        this.view.clear();
        this.view.setStrokeStyle({ width: this.lineWidth, color: this.lineColor });
        this.drawStraightPath();
    }

    drawStraightPath() {
        if (this.path.length > 0) {

            for (let i = 0; i < this.path.length; i++) {
                const info = this.path[i];
                if (info && info.length > 1) {
                    this.view.moveTo(this.points[info[0]].x, this.points[info[0]].y);
                    for (let n = 1; n < info.length; n++) {
                        const p = this.points[info[n]];
                        this.view.lineTo(p.x, p.y);
                    }
                    this.view.stroke();

                    if (info.length > 2 && this.rightType === 1) {
                        // 绘制 T 字形状
                        const lastPoint = this.points[info[info.length - 1]];
                        const secondLastPoint = this.points[info[info.length - 2]];

                        // 计算最后一条线段的方向
                        const dx = lastPoint.x - secondLastPoint.x;
                        const dy = lastPoint.y - secondLastPoint.y;
                        const length = Math.sqrt(dx * dx + dy * dy);
                        const unitX = dx / length;
                        const unitY = dy / length;

                        const tWidth = this.lineWidth * 10; // T 字的宽度

                        // 计算 T 字的中心位置
                        const tCenterX = lastPoint.x;
                        const tCenterY = lastPoint.y;

                        // 绘制 T 字的横杆
                        this.view.moveTo(tCenterX - tWidth * unitY, tCenterY + tWidth * unitX);
                        this.view.lineTo(tCenterX + tWidth * unitY, tCenterY - tWidth * unitX);
                        this.view.stroke();
                    }

                    if(info.length > 2 && this.leftType === 1) {
                        // 绘制 T 字形状
                        const lastPoint = this.points[info[0]];
                        const secondLastPoint = this.points[info[1]];

                        // 计算最后一条线段的方向
                        const dx = lastPoint.x - secondLastPoint.x;
                        const dy = lastPoint.y - secondLastPoint.y;
                        const length = Math.sqrt(dx * dx + dy * dy);
                        const unitX = dx / length;
                        const unitY = dy / length;

                        const tWidth = this.lineWidth * 10; // T 字的宽度

                        // 计算 T 字的中心位置
                        const tCenterX = lastPoint.x;
                        const tCenterY = lastPoint.y;

                        // 绘制 T 字的横杆
                        this.view.moveTo(tCenterX - tWidth * unitY, tCenterY + tWidth * unitX);
                        this.view.lineTo(tCenterX + tWidth * unitY, tCenterY - tWidth * unitX);
                        this.view.stroke();
                    }   
                }
            }
        }
    }

    fixCenter() {
        if (this.path.length > 0 && this.view && this.view.parent && this.__viewDirty) {
            this.__viewDirty = false;
            let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;

            // 计算 AABB (Axis-Aligned Bounding Box)
            for (let i = 0; i < this.path.length; i++) {
                const info = this.path[i];
                for (let n = 0; n < info.length; n++) {
                    const id = info[n];
                    let p = this.points[id];
                    if(p) {
                        if (p.x < minX) minX = p.x;
                        if (p.y < minY) minY = p.y;
                        if (p.x > maxX) maxX = p.x;
                        if (p.y > maxY) maxY = p.y;
                    }
                }
            }

            // 计算中心点
            const centerX = (minX + maxX) / 2;
            const centerY = (minY + maxY) / 2;
            let curpos = this.view.parent ? this.view.parent.toLocal({ x: centerX, y: centerY }, this.view) : { x: centerX, y: centerY };
            for (const key in this.points) {
                if (this.points.hasOwnProperty(key)) {
                    const p = this.points[key];
                    p.x -= centerX;
                    p.y -= centerY;
                }
            }

            this.position.x = curpos.x;
            this.position.y = curpos.y;
            this.view.position.x = curpos.x;
            this.view.position.y = curpos.y;
        }


    }

    applyData(data?: any) {
        super.applyData(data);
        this.__viewDirty = true;
    }

    addPath(points: PathPoint[]) {
        let ids: any[] = []
        points.forEach(p => { this.points[p.id] = p; ids.push(p.id) });
        this.path.push(ids)
        this.fixCenter();
        this.__viewDirty = true;
    }

    fromJson(json: { [key: string]: any; }): void {
        super.fromJson(json);
        this.__viewDirty = true;
    }
}